package com.hualan.utils;

import com.hualan.entity.Users;

import java.lang.invoke.SwitchPoint;
import java.lang.reflect.*;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

//该类主要用来完成对任意Entity数据源的自动化组装
/*
* 1. 当前的工具可以处理所有Entity数据模型  -- 泛型
* 2. 当前工具类必须能够动态识别Entity数据模型中的属性和方法  -- 反射
* */
public class EntityFactory<T> {
    //存放字节管理对象
   private Class<T> obj;
   //定义一个属性存放当前字节管理对象对应的实体对象
   private Object obj1;

    public EntityFactory(Class<T> obj) throws Exception {
        this.obj = obj;
        this.obj1 = this.obj.newInstance();
    }

    //定义功能完成对象的构建
    public T startCombine(ResultSet resultSet) throws Exception{
        //1.获取需要组装的模型的所有属性
        Field[] fields = this.obj.getDeclaredFields();
        //2.根据字段生成所有的setter方法的名称
        List<String> names = this.dealName(fields);
        //3.将每一个数据动态添加到指定的属性中
        Integer index = 0;
        for(Field field:fields){
            this.setFieldValue(field, names.get(index++), resultSet);
        }
        return (T) this.obj1;
    }

    //获取所有的setter方法名称
    public List<String> dealName(Field[] fields){
        List<String> names = new ArrayList<>();
        for(Field field:fields){
            String m_name = field.getName();
            m_name = m_name.substring(0, 1).toUpperCase()+m_name.substring(1);
            names.add("set"+m_name);
        }
        return names;
    }
    //完成每一个属性的数据存储
    public void setFieldValue(Field field, String methodName, ResultSet resultSet) throws Exception{
        //1.获取当前属性的数据类型
        String type = field.getType().getSimpleName();
        if(type.equals("Integer")){
            Integer num = resultSet.getInt(field.getName());
            Method method = this.obj.getMethod(methodName, Integer.class);
            method.invoke(this.obj1, num);
        }else if(type.equals("String")){
            String data = resultSet.getString(field.getName());
            Method method = this.obj.getMethod(methodName, String.class);
            method.invoke(this.obj1, data);
        }else if(type.equals("Date") || type.equals("DateTime")){
            Date data = resultSet.getDate(field.getName());
            Method method = this.obj.getMethod(methodName, Date.class);
            method.invoke(this.obj1, data);
        }else if(type.equals("Double")){
            Double data = resultSet.getDouble(field.getName());
            Method method = this.obj.getMethod(methodName, Double.class);
            method.invoke(this.obj1, data);
        }else if(type.equals("Byte")){
            Byte data = resultSet.getByte(field.getName());
            Method method = this.obj.getMethod(methodName, Byte.class);
            method.invoke(this.obj1, data);
        }else if(type.equals("Blob")){
            Blob data = resultSet.getBlob(field.getName());
            Method method = this.obj.getMethod(methodName, Blob.class);
            method.invoke(this.obj1, data);
        }else{
            if(type.equals("List")){
                return;
            }
            //此时组装的是当前field指向的内部嵌套的自定义对象
            EntityFactory entityFactory = new EntityFactory(field.getType());
            Object data = entityFactory.startCombine(resultSet);
            //获取methodName对应的setter方法
            Method method = this.obj.getMethod(methodName, field.getType());
            method.invoke(this.obj1, data);
        }
    }

    public Class<?> getGenericType(List<?> list) {
        Type genericSuperclass = list.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) genericSuperclass;
            Type[] actualTypeArguments = pt.getActualTypeArguments();
            if (actualTypeArguments.length > 0) {
                return (Class<?>) actualTypeArguments[0];
            }
        }
        return null; // 如果无法确定泛型类型，则返回null
    }
}
